package main

import (
	"fmt"
	"net"
	"strconv"
	"time"

	"gitee.com/konyshe/gogo"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
)

func ListDevice() {
	// Find all devices
	devices, err := pcap.FindAllDevs()
	gogo.CheckError(err)

	// Print device information
	fmt.Println("Devices found:")
	for deviceNum, device := range devices {
		fmt.Println("--------------------------------------")
		fmt.Println("Device Num:", strconv.FormatInt(int64(deviceNum+1), 10))
		fmt.Println("Device Name:", device.Name)
		fmt.Println("Device Description: ", device.Description)
		fmt.Println("Devices addresses: ", device.Description)
		for _, address := range device.Addresses {
			fmt.Println("- IP address: ", address.IP.String())
			fmt.Println("- Subnet mask: ", address.Netmask.String())
		}
	}
}

func LoadFromDevice(recvPort, deviceNum, maxMTU int) {
	devices, err := pcap.FindAllDevs()
	gogo.CheckError(err)

	handle, err := pcap.OpenLive(devices[deviceNum-1].Name, int32(maxMTU), false, 30*time.Second)
	gogo.CheckError(err)
	defer handle.Close()

	gogo.LogInfo("Listen deviceNum: ", strconv.FormatInt(int64(deviceNum), 10))

	filter := "udp and dst port " + strconv.Itoa(recvPort)
	gogo.CheckError(handle.SetBPFFilter(filter))
	gogo.LogInfo("Listen filter: ", filter)

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		applicationLayer := packet.ApplicationLayer()

		pRemoteAddr := new(net.UDPAddr)

		ipLayer := packet.Layer(layers.LayerTypeIPv4)
		if ipLayer != nil {
			ip, _ := ipLayer.(*layers.IPv4)
			pRemoteAddr.IP = ip.SrcIP
		}

		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			udp, _ := udpLayer.(*layers.UDP)
			pRemoteAddr.Port = int(udp.SrcPort)
		}

		if applicationLayer != nil && pProPayloadTask != nil {
			pProPayloadTask.Push(&ProPayloadData{applicationLayer.Payload(), len(applicationLayer.Payload()), pRemoteAddr})
		}
	}
}
